package com.alander.nexusgo.user.service.impl;

import com.alander.nexusgo.framework.redis.starter.key.UserCacheKeyBuilder;
import com.alander.nexusgo.user.mapper.UserTagMapper;
import com.alander.nexusgo.user.model.constants.UserTagFieldNameConstants;
import com.alander.nexusgo.user.model.constants.UserTagsEnum;
import com.alander.nexusgo.user.model.entity.UserTag;
import com.alander.nexusgo.user.service.UserTagService;
import com.alander.nexusgo.user.utils.TagInfoUtils;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.stereotype.Service;

import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * @author alander
 */
@Service
@RequiredArgsConstructor
public class UserTagServiceImpl extends ServiceImpl<UserTagMapper, UserTag> implements UserTagService {

    private final UserTagMapper userTagMapper;

    private final RedisTemplate<String, Object> redisTemplate;

    private final UserCacheKeyBuilder userCacheKeyBuilder;

    @Override
    public List<String> listUserTag(Long userId) {
        // 获取用户标签信息
        UserTag userTag = this.queryByUserIdFromRedis(userId);
        if (userTag == null) {
            return new ArrayList<>();
        }

        List<String> tagList = new ArrayList<>();

        // 遍历所有标签枚举
        for (UserTagsEnum tagEnum : UserTagsEnum.values()) {
            String fieldName = tagEnum.getFieldName();
            long tagValue = tagEnum.getTag();

            // 根据字段名检查对应标签位
            boolean hasTag = false;
            if (UserTagFieldNameConstants.TAG_INFO_01.equals(fieldName)) {
                hasTag = TagInfoUtils.isContain(userTag.getTagInfo01(), tagValue);
            } else if (UserTagFieldNameConstants.TAG_INFO_02.equals(fieldName)) {
                hasTag = TagInfoUtils.isContain(userTag.getTagInfo02(), tagValue);
            } else if (UserTagFieldNameConstants.TAG_INFO_03.equals(fieldName)) {
                hasTag = TagInfoUtils.isContain(userTag.getTagInfo03(), tagValue);
            }

            // 如果标签被设置，添加到结果列表
            if (hasTag) {
                tagList.add(tagEnum.getDesc());
            }
        }

        return tagList;
    }

    @Override
    public List<UserTagsEnum> listUserTagEnums(Long userId) {
        // 获取用户标签信息
        UserTag userTag = this.queryByUserIdFromRedis(userId);
        if (userTag == null) {
            return new ArrayList<>();
        }

        List<UserTagsEnum> tagList = new ArrayList<>();

        // 遍历所有标签枚举
        for (UserTagsEnum tagEnum : UserTagsEnum.values()) {
            String fieldName = tagEnum.getFieldName();
            long tagValue = tagEnum.getTag();

            // 根据字段名检查对应标签位
            boolean hasTag = false;
            if (UserTagFieldNameConstants.TAG_INFO_01.equals(fieldName)) {
                hasTag = TagInfoUtils.isContain(userTag.getTagInfo01(), tagValue);
            } else if (UserTagFieldNameConstants.TAG_INFO_02.equals(fieldName)) {
                hasTag = TagInfoUtils.isContain(userTag.getTagInfo02(), tagValue);
            } else if (UserTagFieldNameConstants.TAG_INFO_03.equals(fieldName)) {
                hasTag = TagInfoUtils.isContain(userTag.getTagInfo03(), tagValue);
            }

            // 如果标签被设置，添加到结果列表
            if (hasTag) {
                tagList.add(tagEnum);
            }
        }

        return tagList;
    }



    @Override
    public boolean setTag(Long userId, UserTagsEnum userTagsEnum) {
        boolean updateStatus = userTagMapper.setTag(userId, userTagsEnum.getFieldName(), userTagsEnum.getTag()) > 0;
        if (updateStatus) {
            deleteUserTagFromRedis(userId);
            return true;
        }
        String setNxKey = userCacheKeyBuilder.buildUserTagLockKey(String.valueOf(userId));
        String setNxResult = redisTemplate.execute(new RedisCallback<String>() {
            @Override
            public String doInRedis(RedisConnection connection) throws DataAccessException {
                RedisSerializer keySerializer = redisTemplate.getKeySerializer();
                RedisSerializer valueSerializer = redisTemplate.getValueSerializer();
                return (String) connection.execute("set", keySerializer.serialize(setNxKey), valueSerializer.serialize("-1"), "NX".getBytes(StandardCharsets.UTF_8), "EX".getBytes(StandardCharsets.UTF_8), "3".getBytes(StandardCharsets.UTF_8));
            }
        });
        if (!"OK".equals(setNxResult)) {
            return false;
        }
        UserTag userTag = userTagMapper.selectById(userId);
        if (userTag != null) {
            return false;
        }
        userTag = new UserTag();
        userTag.setUserId(userId);
        userTagMapper.insert(userTag);
        updateStatus = userTagMapper.setTag(userId, userTagsEnum.getFieldName(), userTagsEnum.getTag()) > 0;
        redisTemplate.delete(setNxKey);
        return updateStatus;
    }

    @Override
    public boolean cancelTag(Long userId, UserTagsEnum userTagsEnum) {
        boolean cancelStatus = userTagMapper.cancelTag(userId, userTagsEnum.getFieldName(), userTagsEnum.getTag()) > 0;
        if (!cancelStatus) {
            return false;
        }
        deleteUserTagFromRedis(userId);
        return true;
    }

    @Override
    public boolean containTag(Long userId, UserTagsEnum userTagsEnum) {
        UserTag userTag = this.queryByUserIdFromRedis(userId);
        if (userTag == null) {
            return false;
        }
        String queryFieldName = userTagsEnum.getFieldName();
        //需要根据标签枚举中的fieldName来识别需要匹配MySQL表中哪个字段的标签值
        if (UserTagFieldNameConstants.TAG_INFO_01.equals(queryFieldName)) {
            return TagInfoUtils.isContain(userTag.getTagInfo01(), userTagsEnum.getTag());
        } else if (UserTagFieldNameConstants.TAG_INFO_02.equals(queryFieldName)) {
            return TagInfoUtils.isContain(userTag.getTagInfo02(), userTagsEnum.getTag());
        } else if (UserTagFieldNameConstants.TAG_INFO_03.equals(queryFieldName)) {
            return TagInfoUtils.isContain(userTag.getTagInfo03(), userTagsEnum.getTag());
        }
        return false;
    }


    /**
     * 从redis中删除用户标签对象
     *
     * @param userId
     */
    private void deleteUserTagFromRedis(Long userId) {
        String redisKey = userCacheKeyBuilder.buildUserTagKey(String.valueOf(userId));
        redisTemplate.delete(redisKey);
    }

    /**
     * 从redis中查询用户标签对象
     *
     * @param userId
     * @return
     */
    private UserTag queryByUserIdFromRedis(Long userId) {
        String redisKey = userCacheKeyBuilder.buildUserTagKey(String.valueOf(userId));
        UserTag userTag = (UserTag) redisTemplate.opsForValue().get(redisKey);
        if (userTag != null) {
            return userTag;
        }
        userTag = userTagMapper.selectById(userId);
        if (userTag == null) {
            return null;
        }
        redisTemplate.opsForValue().set(redisKey, userTag);
        redisTemplate.expire(redisKey, 30, TimeUnit.MINUTES);
        return userTag;
    }
}




